local _ENV = Dora

print("=== Script Start ===")

-- 测试基本功能
local function testBasics()
    print("1. Testing Director...")
    if not Director then
        print("   Director: FAILED")
        return false
    end
    print("   Director: OK")
    
    print("2. Testing View.size...")
    if not (View and View.size) then
        print("   View.size: FAILED")
        return false
    end
    print("   View.size: OK (" .. View.size.width .. " x " .. View.size.height .. ")")
    
    return true
end

if not testBasics() then
    print("=== Basic tests FAILED ===")
    return
end

print("=== Basic tests PASSED ===")

-- ============================================
-- 游戏配置
-- ============================================

local TILE_SIZE = 60
local GRID_SIZE = 8
local MOVE_DURATION = 0.2
local MAX_ENERGY = 200
local ENERGY_COST_MOVE = 5
local ENERGY_COST_PUSH = 8
local ENERGY_COST_ROTATE = 3

local map = {
    {3,3,3,3,3,3,3,3},
    {3,3,3,3,3,3,3,3},
    {3,3,3,3,3,3,3,3},
    {1,1,1,3,3,1,1,1},
    {1,1,1,3,3,1,1,1},
    {3,3,3,3,3,3,3,3},
    {3,3,3,3,3,3,3,3},
    {3,3,3,3,3,3,3,3}
}

-- ============================================
-- 游戏开始界面
-- ============================================

print("Creating start screen...")

-- 使用游戏世界的尺寸而不是屏幕尺寸
local DESIGN_WIDTH = GRID_SIZE * TILE_SIZE
local DESIGN_HEIGHT = GRID_SIZE * TILE_SIZE

local startScreen = Node()
startScreen.zOrder = 10000

-- 半透明黑色背景 - 使用设计尺寸
local bgOverlay = DrawNode()
bgOverlay:drawPolygon({
    Vec2(0, 0),
    Vec2(DESIGN_WIDTH, 0),
    Vec2(DESIGN_WIDTH, DESIGN_HEIGHT),
    Vec2(0, DESIGN_HEIGHT)
}, Color(0xcc000000))
bgOverlay.position = Vec2(0, 0)
startScreen:addChild(bgOverlay)

-- 游戏标题
local titleLabel = nil
pcall(function()
    titleLabel = Label("sarasa-mono-sc-regular", 48)
    if not titleLabel then
        titleLabel = Label()
        if titleLabel then
            titleLabel.fontSize = 48
        end
    end
    if titleLabel then
        titleLabel.text = "推箱子游戏"
        titleLabel.color = Color(0xffffffff)
        titleLabel.position = Vec2(DESIGN_WIDTH / 2, DESIGN_HEIGHT / 2 + 60)
        startScreen:addChild(titleLabel)
    end
end)

-- 提示文字
local hintLabel = nil
pcall(function()
    hintLabel = Label("sarasa-mono-sc-regular", 24)
    if not hintLabel then
        hintLabel = Label()
        if hintLabel then
            hintLabel.fontSize = 24
        end
    end
    if hintLabel then
        hintLabel.text = "按任意键开始游戏"
        hintLabel.color = Color(0xffffff00)
        hintLabel.position = Vec2(DESIGN_WIDTH / 2, DESIGN_HEIGHT / 2 - 20)
        startScreen:addChild(hintLabel)

        -- 添加闪烁效果
        hintLabel:perform(Sequence(
            Opacity(0.8, 1, 0.3),
            Opacity(0.8, 0.3, 1),
            Loop()
        ))
    end
end)

-- 游戏说明
local infoLabel = nil
pcall(function()
    infoLabel = Label("sarasa-mono-sc-regular", 18)
    if not infoLabel then
        infoLabel = Label()
        if infoLabel then
            infoLabel.fontSize = 18
        end
    end
    if infoLabel then
        infoLabel.text = "W/A/S/D: 移动 | Space: 旋转砖块 | R: 重新开始"
        infoLabel.color = Color(0xffaaaaaa)
        infoLabel.position = Vec2(DESIGN_WIDTH / 2, DESIGN_HEIGHT / 2 - 80)
        startScreen:addChild(infoLabel)
    end
end)

Director.entry:addChild(startScreen)
print("Start screen created")

-- ============================================
-- 背景音乐
-- ============================================

print("Loading background music...")

-- 使用正确的 Dora Audio API: playStream()
local bgMusicStarted = false

-- 尝试多个音乐文件名和格式
local musicFiles = {
    "music.ogg",
    "music.mp3",
    "music.wav",
    "music.OGG",
    "music.MP3",
}

-- 尝试多个可能的路径
local searchPaths = {"", "audio/", "Audio/", "music/", "Music/", "sound/", "Sound/"}

print("Attempting to play background music...")

for _, audioFile in ipairs(musicFiles) do
    if bgMusicStarted then break end

    for _, prefix in ipairs(searchPaths) do
        local fullPath = prefix .. audioFile

        -- 使用 playStream() 方法播放音频流
        local success, err = pcall(function()
            Audio:playStream(fullPath, true, 0.0)
        end)

        if success then
            print("✓ Successfully started music: " .. fullPath)
            bgMusicStarted = true
            break
        else
            -- 只打印第一个路径的失败信息，避免日志过多
            if prefix == "" then
                print("✗ Failed to load " .. audioFile .. ": " .. tostring(err))
            end
        end
    end
end

if bgMusicStarted then
    print("Background music is now playing (looping)")
else
    print("")
    print("========================================")
    print("WARNING: Could not load background music")
    print("========================================")
    print("Possible reasons:")
    print("1. Audio file format issue - Try converting to:")
    print("   - OGG Vorbis format (recommended)")
    print("   - MP3 format (widely supported)")
    print("   - WAV format (uncompressed, larger)")
    print("")
    print("2. File may be corrupted or encoded incorrectly")
    print("")
    print("3. Suggested tools to re-encode:")
    print("   - Audacity (free, cross-platform)")
    print("   - FFmpeg: ffmpeg -i music.mp3 -c:a libvorbis music.ogg")
    print("")
    print("Game will continue without music...")
    print("========================================")
    print("")
end

-- ============================================
-- 游戏初始化函数
-- ============================================

local function initializeGame()
print("Creating game world...")

local playerGridX = 3
local playerGridY = 1
local isMoving = false
local currentEnergy = MAX_ENERGY
local gameOver = false
local gameWon = false

-- 目标区域定义（地图中央的空缺区域）
local targetCells = {
    {3, 3}, {4, 3}, {3, 4}, {4, 4}
}

-- 创建物理世界
local world = PhysicsWorld()
if not world then
    print("ERROR: Failed to create PhysicsWorld!")
    return
end
world.showDebug = true

-- 确保 Director.entry 存在
if not Director.entry then
    print("ERROR: Director.entry is nil!")
    return
end

Director.entry:addChild(world)
print("PhysicsWorld created and added to scene")

-- 创建图片或纯色方块
local function createColoredTile(size, color)
    local draw = DrawNode()
    local half = size * 0.5
    draw:drawPolygon({
        Vec2(-half, -half),
        Vec2(half, -half),
        Vec2(half, half),
        Vec2(-half, half)
    }, color)
    return draw
end

-- 加载图片贴图
local function createSprite(filename, width, height)
    local sprite
    local success = pcall(function()
        sprite = Sprite(filename)
    end)

    if success and sprite then
        -- 根据需要调整尺寸
        if width and height then
            sprite.scaleX = width / sprite.width
            sprite.scaleY = height / sprite.height
        end
        return sprite
    end
    return nil
end

-- 创建整个地图的背景图片
print("Creating map background...")
local mapBackground = createSprite("map.png", GRID_SIZE * TILE_SIZE, GRID_SIZE * TILE_SIZE)
if mapBackground then
    mapBackground.position = Vec2(GRID_SIZE * TILE_SIZE / 2, GRID_SIZE * TILE_SIZE / 2)
    mapBackground.zOrder = -10  -- 确保在最底层
    Director.entry:addChild(mapBackground)
    print("Map background created and stretched to full size")
else
    print("Warning: Could not load map.png, using colored background")
    -- 如果加载失败，创建一个纯色背景
    local bgDraw = DrawNode()
    bgDraw:drawPolygon({
        Vec2(0, 0),
        Vec2(GRID_SIZE * TILE_SIZE, 0),
        Vec2(GRID_SIZE * TILE_SIZE, GRID_SIZE * TILE_SIZE),
        Vec2(0, GRID_SIZE * TILE_SIZE)
    }, Color(0xff303030))
    bgDraw.zOrder = -10
    Director.entry:addChild(bgDraw)
end

-- 创建瓦片
local function createTile(x, y, t)
    local px = x * TILE_SIZE + TILE_SIZE * 0.5
    local py = y * TILE_SIZE + TILE_SIZE * 0.5

    if t == 1 then
        -- 墙壁 - 保留碰撞判定但不显示视觉效果
        local def = BodyDef()
        def.type = "Static"
        def:attachPolygon(TILE_SIZE, TILE_SIZE)
        local b = Body(def, world)
        if b then
            b.position = Vec2(px, py)
            b:addTo(Director.entry)
        end
    elseif t == 3 then
        -- 地板 - 使用整体地图背景，无需单独创建
        return
    end
end

print("Creating map tiles...")
for row = 1, GRID_SIZE do
    for col = 1, GRID_SIZE do
        local gx = col - 1
        local gy = GRID_SIZE - row
        createTile(gx, gy, map[row][col])
    end
end
print("Map tiles created")

-- 标记目标区域
print("Marking target areas...")
for _, target in ipairs(targetCells) do
    local gx, gy = target[1], target[2]
    local px = gx * TILE_SIZE + TILE_SIZE * 0.5
    local py = (GRID_SIZE - gy - 1) * TILE_SIZE + TILE_SIZE * 0.5

    -- 创建目标标记（半透明绿色方块）
    local marker = DrawNode()
    marker:drawPolygon({
        Vec2(-TILE_SIZE * 0.3, -TILE_SIZE * 0.3),
        Vec2(TILE_SIZE * 0.3, -TILE_SIZE * 0.3),
        Vec2(TILE_SIZE * 0.3, TILE_SIZE * 0.3),
        Vec2(-TILE_SIZE * 0.3, TILE_SIZE * 0.3)
    }, Color(0x4400ff00), 2, Color(0xff00ff00))
    marker.position = Vec2(px, py)
    marker.zOrder = -0.5
    Director.entry:addChild(marker)
end
print("Target areas marked")

-- 边界墙
local function createBoundary()
    local w, h = GRID_SIZE * TILE_SIZE, GRID_SIZE * TILE_SIZE
    local function wall(width, height, pos)
        local def = BodyDef()
        def.type = "Static"
        def:attachPolygon(width, height)
        local b = Body(def, world)
        if b then
            b.position = pos
            b:addTo(Director.entry)
        end
    end
    wall(10, h + 100, Vec2(-TILE_SIZE/2 - 5, h/2))
    wall(10, h + 100, Vec2(w - TILE_SIZE/2 + 5, h/2))
    wall(w + 100, 10, Vec2(w/2, h - TILE_SIZE/2 + 5))
    wall(w + 100, 10, Vec2(w/2, -TILE_SIZE/2 - 5))
end
createBoundary()
print("Boundaries created")

-- 能量显示
local energyDisplay = Node()
energyDisplay.anchor = Vec2(0, 1)
energyDisplay.position = Vec2(10, GRID_SIZE * TILE_SIZE - 10)
energyDisplay.zOrder = 1000

local bgWidth, bgHeight = 150, 30
local bg = DrawNode()
bg:drawPolygon({
    Vec2(0, -bgHeight),
    Vec2(bgWidth, -bgHeight),
    Vec2(bgWidth, 0),
    Vec2(0, 0)
}, Color(0xaa000000), 2, Color(0xffffffff))
energyDisplay:addChild(bg)

-- 创建文字标签（使用默认字体）
local energyText = nil
pcall(function()
    -- 修复：使用正确的 Label 构造函数
    energyText = Label("sarasa-mono-sc-regular", 20)
    if not energyText then
        -- 如果找不到字体，尝试创建一个简单的 Label
        energyText = Label()
        if energyText then
            energyText.fontSize = 20
        end
    end
    if energyText then
        energyText.anchor = Vec2(0, 1)
        energyText.position = Vec2(5, -5)
        energyText.text = string.format("Energy: %d/%d", currentEnergy, MAX_ENERGY)
        energyText.color = Color(0xff00ff00)
        energyDisplay:addChild(energyText)
        print("Energy text label created")
    end
end)

if not energyText then
    print("Warning: Could not create text label, continuing without it")
end

Director.entry:addChild(energyDisplay)

local function updateEnergyBar()
    if energyText then
        local c = currentEnergy < 30 and Color(0xffff0000) or Color(0xff00ff00)
        energyText.text = string.format("Energy: %d/%d", currentEnergy, MAX_ENERGY)
        energyText.color = c
    end
    print(string.format("Energy: %d/%d", currentEnergy, MAX_ENERGY))
end
updateEnergyBar()

local function consumeEnergy(n)
    if gameOver then return false end
    if currentEnergy < n then 
        if not gameOver then
            currentEnergy = 0
            updateEnergyBar()
            gameOver = true
            print("Game Over! Press R to restart.")
        end
        return false 
    end
    currentEnergy = currentEnergy - n
    updateEnergyBar()
    
    if currentEnergy <= 0 and not gameOver then
        currentEnergy = 0
        updateEnergyBar()
        gameOver = true
        print("Game Over! Press R to restart.")
    end
    
    return true
end

-- 玩家
print("Creating player...")
local pdef = BodyDef()
pdef.type = "Kinematic"
pdef:attachPolygon(TILE_SIZE * 0.8, TILE_SIZE * 0.8, 1, 0, 0)
pdef.fixedRotation = true
local playerPos = Vec2(playerGridX * TILE_SIZE + TILE_SIZE * 0.5, (GRID_SIZE - playerGridY - 1) * TILE_SIZE + TILE_SIZE * 0.5)
local player = Body(pdef, world, playerPos)
if player then
    player.group = 0
    local visual = DrawNode()
    visual:drawPolygon({
        Vec2(-TILE_SIZE * 0.4, -TILE_SIZE * 0.4),
        Vec2(TILE_SIZE * 0.4, -TILE_SIZE * 0.4),
        Vec2(TILE_SIZE * 0.4, TILE_SIZE * 0.4),
        Vec2(-TILE_SIZE * 0.4, TILE_SIZE * 0.4)
    }, Color(0xff00ff00))
    player:addChild(visual)
    player:addTo(Director.entry)
    print("Player created")
else
    print("Failed to create player!")
    return
end

-- 砖块
local bricks = {}
local function horizVerts()
    return {
        Vec2(-TILE_SIZE, -TILE_SIZE * 0.5),
        Vec2(TILE_SIZE, -TILE_SIZE * 0.5),
        Vec2(TILE_SIZE, TILE_SIZE * 0.5),
        Vec2(-TILE_SIZE, TILE_SIZE * 0.5)
    }
end

local function vertVerts()
    return {
        Vec2(-TILE_SIZE * 0.5, -TILE_SIZE),
        Vec2(TILE_SIZE * 0.5, -TILE_SIZE),
        Vec2(TILE_SIZE * 0.5, TILE_SIZE),
        Vec2(-TILE_SIZE * 0.5, TILE_SIZE)
    }
end

local function createBrick(gx, gy, id)
    print("Creating brick " .. id .. " at grid position " .. gx .. "," .. gy)
    local verts = horizVerts()
    local def = BodyDef()
    def.type = "Kinematic"
    def.fixedRotation = true

    -- 先附加物理形状
    local success = pcall(function()
        def:attachPolygon(verts, 1, 0, 0)
    end)

    if not success then
        print("Failed to attach polygon to brick " .. id)
        return
    end

    local pos = Vec2(gx * TILE_SIZE + TILE_SIZE, (GRID_SIZE - gy - 1) * TILE_SIZE + TILE_SIZE * 0.5)
    local b = Body(def, world, pos)
    if not b then
        print("Failed to create brick body at " .. gx .. "," .. gy)
        return
    end
    b.group = 1

    -- 尝试加载砖块图片，失败则用纯色
    local visual = createSprite("brick.png", TILE_SIZE * 2, TILE_SIZE)
    if not visual then
        visual = createColoredTile(TILE_SIZE, Color(0xffff6600))
        if visual then
            visual.scaleX = 2
        end
    end
    if visual then
        b:addChild(visual)
    end
    b:addTo(Director.entry)

    local data = {body = b, rotation = 0, id = id, gridX = gx, gridY = gy, isMoving = false, verts = verts}
    bricks[#bricks + 1] = data
    print("Brick " .. id .. " successfully created")
end

-- 砖块占据的格子
local function occupiedCells(brick)
    local r = brick.rotation
    local gx, gy = brick.gridX, brick.gridY
    if r == 0 then
        return {{gx,gy},{gx+1,gy}}
    else
        return {{gx,gy},{gx,gy+1}}
    end
end

local function cellHasBrick(gx, gy)
    for _, b in ipairs(bricks) do
        for _, c in ipairs(occupiedCells(b)) do
            if c[1] == gx and c[2] == gy then
                return true, b
            end
        end
    end
    return false
end

-- 随机生成砖块的函数
local function randomizeBricks()
    local maxBricks = 2
    local bricksCreated = 0
    local playerStartPos = {x = playerGridX, y = playerGridY} -- 玩家初始位置

    -- 检查位置是否可以放置横向砖块
    local function canPlaceBrick(gx, gy)
        -- 检查是否超出地图边界
        if gx < 0 or gx + 1 >= GRID_SIZE or gy < 0 or gy >= GRID_SIZE then
            return false
        end

        -- 检查两个格子是否都是地板
        local row1 = GRID_SIZE - gy
        local row2 = GRID_SIZE - gy
        local col1 = gx + 1
        local col2 = gx + 2

        if map[row1][col1] ~= 3 or map[row2][col2] ~= 3 then
            return false
        end

        -- 检查是否会覆盖玩家初始位置
        if (gx == playerStartPos.x and gy == playerStartPos.y) or (gx + 1 == playerStartPos.x and gy == playerStartPos.y) then
            return false
        end

        -- 检查是否已经有砖块占据这两个格子
        if cellHasBrick(gx, gy) or cellHasBrick(gx + 1, gy) then
            return false
        end

        return true
    end

    -- 随机生成砖块
    while bricksCreated < maxBricks do
        local gx = math.random(0, GRID_SIZE - 2) -- 横向砖块需要两个格子，所以gx最大为GRID_SIZE-2
        local gy = math.random(0, GRID_SIZE - 1)

        if canPlaceBrick(gx, gy) then
            bricksCreated = bricksCreated + 1
            createBrick(gx, gy, bricksCreated)
        end
    end
end

print("Creating bricks...")
randomizeBricks()
print("Bricks created: " .. #bricks)
print("Target area: (3,3), (4,3), (3,4), (4,4)")
print("TIP: Push both bricks into the green target area to win!")

-- 前置声明 showVictoryScreen 函数
local showVictoryScreen

-- 检查是否所有砖块都在目标区域内
local function checkVictory()
    if gameWon or gameOver then return end

    print("Checking victory condition...")

    -- 收集所有砖块占据的格子
    local brickCells = {}
    for _, brick in ipairs(bricks) do
        local cells = occupiedCells(brick)
        for _, cell in ipairs(cells) do
            table.insert(brickCells, {cell[1], cell[2]})
            print(string.format("  Brick cell: (%d, %d)", cell[1], cell[2]))
        end
    end

    -- 检查是否所有砖块格子都在目标区域内
    for _, bCell in ipairs(brickCells) do
        local inTarget = false
        for _, tCell in ipairs(targetCells) do
            if bCell[1] == tCell[1] and bCell[2] == tCell[2] then
                inTarget = true
                break
            end
        end
        if not inTarget then
            print(string.format("  Cell (%d, %d) is NOT in target area", bCell[1], bCell[2]))
            return false
        end
    end

    -- 检查是否所有目标格子都被砖块占据
    for _, tCell in ipairs(targetCells) do
        local hasBrick = false
        for _, bCell in ipairs(brickCells) do
            if bCell[1] == tCell[1] and bCell[2] == tCell[2] then
                hasBrick = true
                break
            end
        end
        if not hasBrick then
            print(string.format("  Target cell (%d, %d) is NOT covered", tCell[1], tCell[2]))
            return false
        end
    end

    -- 所有条件满足，游戏胜利！
    print("All victory conditions met!")
    gameWon = true
    showVictoryScreen()
    return true
end

-- 显示胜利界面
local victoryScreen = nil  -- 保存胜利界面的引用

showVictoryScreen = function()
    print("=== VICTORY! ===")

    victoryScreen = Node()
    victoryScreen.zOrder = 10001

    -- 半透明背景
    local bgOverlay = DrawNode()
    bgOverlay:drawPolygon({
        Vec2(0, 0),
        Vec2(GRID_SIZE * TILE_SIZE, 0),
        Vec2(GRID_SIZE * TILE_SIZE, GRID_SIZE * TILE_SIZE),
        Vec2(0, GRID_SIZE * TILE_SIZE)
    }, Color(0xdd000000))
    victoryScreen:addChild(bgOverlay)

    -- 胜利标题
    pcall(function()
        local titleLabel = Label("sarasa-mono-sc-regular", 60)
        if not titleLabel then
            titleLabel = Label()
            if titleLabel then titleLabel.fontSize = 60 end
        end
        if titleLabel then
            titleLabel.text = "胜利!"
            titleLabel.color = Color(0xffffd700)
            titleLabel.position = Vec2(GRID_SIZE * TILE_SIZE / 2, GRID_SIZE * TILE_SIZE / 2 + 80)
            victoryScreen:addChild(titleLabel)

            -- 添加闪烁动画
            titleLabel:perform(Sequence(
                Scale(0.3, 1.0, 1.2, Ease.InOutQuad),
                Scale(0.3, 1.2, 1.0, Ease.InOutQuad),
                Loop()
            ))
        end
    end)

    -- 显示剩余能量
    pcall(function()
        local energyLabel = Label("sarasa-mono-sc-regular", 28)
        if not energyLabel then
            energyLabel = Label()
            if energyLabel then energyLabel.fontSize = 28 end
        end
        if energyLabel then
            energyLabel.text = string.format("剩余能量: %d", currentEnergy)
            energyLabel.color = Color(0xff00ff00)
            energyLabel.position = Vec2(GRID_SIZE * TILE_SIZE / 2, GRID_SIZE * TILE_SIZE / 2 + 20)
            victoryScreen:addChild(energyLabel)
        end
    end)

    -- 提示信息
    pcall(function()
        local hintLabel = Label("sarasa-mono-sc-regular", 22)
        if not hintLabel then
            hintLabel = Label()
            if hintLabel then hintLabel.fontSize = 22 end
        end
        if hintLabel then
            hintLabel.text = "按 R 键重新开始"
            hintLabel.color = Color(0xffffffff)
            hintLabel.position = Vec2(GRID_SIZE * TILE_SIZE / 2, GRID_SIZE * TILE_SIZE / 2 - 40)
            victoryScreen:addChild(hintLabel)
        end
    end)

    Director.entry:addChild(victoryScreen)
    print("Victory screen displayed")
end

local function canPush(brick, dx, dy)
    local cells = occupiedCells(brick)
    for _, c in ipairs(cells) do
        local nx, ny = c[1] + dx, c[2] + dy
        if nx < 0 or nx >= GRID_SIZE or ny < 0 or ny >= GRID_SIZE then
            return false
        end
        if map[GRID_SIZE - ny][nx + 1] == 1 then
            return false
        end
        local has, other = cellHasBrick(nx, ny)
        if has and other ~= brick then
            return false
        end
    end
    return true
end

local function rotateBrick(brick)
    if brick.isMoving then return end
    brick.isMoving = true
    local newRot = (brick.rotation + 1) % 2
    local newVerts = newRot == 0 and horizVerts() or vertVerts()
    local gx, gy = brick.gridX, brick.gridY
    local tempOld = brick.rotation
    brick.rotation = newRot
    local cells = occupiedCells(brick)
    local ok = true
    for _, c in ipairs(cells) do
        local cx, cy = c[1], c[2]
        if cx < 0 or cx >= GRID_SIZE or cy < 0 or cy >= GRID_SIZE then
            ok = false
            break
        end
        if map[GRID_SIZE - cy][cx + 1] == 1 then
            ok = false
            break
        end
        local has, other = cellHasBrick(cx, cy)
        if has and other ~= brick then
            ok = false
            break
        end
    end
    if not ok then
        brick.rotation = tempOld
        brick.isMoving = false
        return
    end

    brick.verts = newVerts
    local oldBody = brick.body
    local def = BodyDef()
    def.type = "Kinematic"
    def:attachPolygon(newVerts, 1, 0, 0)
    def.fixedRotation = true
    local pos
    if newRot == 0 then
        pos = Vec2(gx * TILE_SIZE + TILE_SIZE, (GRID_SIZE - gy - 1) * TILE_SIZE + TILE_SIZE * 0.5)
    else
        pos = Vec2(gx * TILE_SIZE + TILE_SIZE * 0.5, (GRID_SIZE - gy - 1) * TILE_SIZE + TILE_SIZE * 0.5 - TILE_SIZE * 0.5)
    end
    local newBody = Body(def, world, pos)
    if newBody then
        newBody.group = 1
        -- 尝试加载砖块图片
        local visual
        if newRot == 0 then
            -- 横向砖块
            visual = createSprite("brick.png", TILE_SIZE * 2, TILE_SIZE)
            if not visual then
                visual = createColoredTile(TILE_SIZE, Color(0xffff6600))
                visual.scaleX = 2
            end
        else
            -- 竖向砖块
            visual = createSprite("brick.png", TILE_SIZE, TILE_SIZE * 2)
            if not visual then
                visual = createColoredTile(TILE_SIZE, Color(0xffff6600))
                visual.scaleY = 2
            end
        end
        if visual then
            newBody:addChild(visual)
        end
        newBody:addTo(Director.entry)
        brick.body = newBody
        oldBody:removeFromParent()
    end
    brick.isMoving = false
end

local function moveTo(gx, gy)
    if gx < 0 or gx >= GRID_SIZE or gy < 0 or gy >= GRID_SIZE then return end
    if map[GRID_SIZE - gy][gx + 1] == 1 then return end

    local hasBrick, brick = cellHasBrick(gx, gy)
    if hasBrick then
        local dx, dy = gx - playerGridX, gy - playerGridY
        if not canPush(brick, dx, dy) then return end
        if not consumeEnergy(ENERGY_COST_PUSH) then return end

        isMoving = true
        brick.isMoving = true
        brick.gridX = brick.gridX + dx
        brick.gridY = brick.gridY + dy
        local targetPos
        if brick.rotation == 0 then
            targetPos = Vec2(brick.gridX * TILE_SIZE + TILE_SIZE, (GRID_SIZE - brick.gridY - 1) * TILE_SIZE + TILE_SIZE * 0.5)
        else
            targetPos = Vec2(brick.gridX * TILE_SIZE + TILE_SIZE * 0.5, (GRID_SIZE - brick.gridY - 1) * TILE_SIZE + TILE_SIZE * 0.5 - TILE_SIZE * 0.5)
        end
        brick.body:perform(Sequence(
            Spawn(
                X(MOVE_DURATION, brick.body.position.x, targetPos.x, Ease.InOutQuad),
                Y(MOVE_DURATION, brick.body.position.y, targetPos.y, Ease.InOutQuad)
            ),
            Event("BrickDone")
        ))
        brick.body:slot("BrickDone", function()
            brick.isMoving = false
            -- 砖块移动完成后检查胜利条件
            checkVictory()
        end)
    else
        if not consumeEnergy(ENERGY_COST_MOVE) then return end
    end

    isMoving = true
    playerGridX, playerGridY = gx, gy
    local targetPos = Vec2(gx * TILE_SIZE + TILE_SIZE * 0.5, (GRID_SIZE - gy - 1) * TILE_SIZE + TILE_SIZE * 0.5)
    player:perform(Sequence(
        Spawn(
            X(MOVE_DURATION, player.position.x, targetPos.x, Ease.InOutQuad),
            Y(MOVE_DURATION, player.position.y, targetPos.y, Ease.InOutQuad)
        ),
        Event("MoveDone")
    ))
    player:slot("MoveDone", function()
        isMoving = false
        -- 玩家移动完成后也检查胜利条件（虽然不推砖块，但保持一致性）
        checkVictory()
    end)
end

-- 键盘控制
print("Setting up keyboard controls...")
local ctrl = Node()
ctrl.keyboardEnabled = true
Director.entry:addChild(ctrl)
ctrl:slot("KeyDown", function(k)
    if k == "R" then
        print("Restarting game...")
        currentEnergy = MAX_ENERGY
        playerGridX = 3
        playerGridY = 1
        isMoving = false
        gameOver = false
        gameWon = false

        -- 移除胜利界面
        if victoryScreen then
            victoryScreen:removeFromParent()
            victoryScreen = nil
        end

        local playerPos = Vec2(playerGridX * TILE_SIZE + TILE_SIZE * 0.5, (GRID_SIZE - playerGridY - 1) * TILE_SIZE + TILE_SIZE * 0.5)
        player.position = playerPos

        for _, brick in ipairs(bricks) do
            if brick.body then
                brick.body:removeFromParent()
            end
        end
        bricks = {}

        -- 随机生成砖块
        randomizeBricks()

        updateEnergyBar()
        print("Game restarted!")
        return
    end

    if isMoving or gameOver or gameWon then return end
    if k == "W" then moveTo(playerGridX, playerGridY - 1)
    elseif k == "S" then moveTo(playerGridX, playerGridY + 1)
    elseif k == "A" then moveTo(playerGridX - 1, playerGridY)
    elseif k == "D" then moveTo(playerGridX + 1, playerGridY)
    elseif k == "Space" then
        local dirs = {{0,-1},{0,1},{-1,0},{1,0}}
        for _, d in ipairs(dirs) do
            local has, b = cellHasBrick(playerGridX + d[1], playerGridY + d[2])
            if has and consumeEnergy(ENERGY_COST_ROTATE) then
                rotateBrick(b)
                return
            end
        end
    end
end)

-- 屏幕适配
local DesignWidth = GRID_SIZE * TILE_SIZE
local DesignHeight = GRID_SIZE * TILE_SIZE

local function adapt()
    -- 添加更多的安全检查
    if not Director then
        print("ERROR: Director is nil")
        return
    end
    if not Director.currentCamera then
        print("Warning: Camera not ready yet, skipping adapt")
        return
    end
    if not View or not View.size then
        print("Warning: View.size not available")
        return
    end

    local winW, winH = View.size.width, View.size.height
    if winW <= 0 or winH <= 0 then
        print("Warning: Invalid window size")
        return
    end

    local scale = math.min(winW / DesignWidth, winH / DesignHeight)
    Director.currentCamera.zoom = scale
    Director.currentCamera.position = Vec2(DesignWidth / 2, DesignHeight / 2)
end

print("Setting up camera...")
-- 初始化相机
adapt()

-- 监听窗口大小变化
if Director.entry.schedule then
    Director.entry:schedule(function()
        adapt()
    end)
end

print("=== Game initialization complete ===")
print("Controls: W/A/S/D to move, Space to rotate bricks, R to restart")
print("- Green square: Player")
print("- Gray blocks: Walls")
print("- Orange rectangles: Movable bricks")

end -- 结束 initializeGame() 函数

-- 监听按键开始游戏
local startCtrl = Node()
startCtrl.keyboardEnabled = true
Director.entry:addChild(startCtrl)

-- 开始游戏的函数
local function startGame()
    print("Starting game...")
    startScreen:removeFromParent()
    startCtrl:removeFromParent()
    initializeGame()
end

startCtrl:slot("KeyDown", function(k)
    startGame()
end)

print("Waiting for player to press any key...")